package pers.cz.netty.filter;

import java.util.List;

/**
 * @version 1.0
 * @description: 规则管道，所有的规则校验都要通过该管道
 * @author: ChengZhi 0336
 * @create: 2024-08-12 12:09
 **/
public class Pipeline<T, O> implements IFilter<T, O> {

    private final AbstractFilterHandlerContext<T,O> head;

    private final AbstractFilterHandlerContext<T,O> tail;

    public Pipeline() {
        head = new HeadContext(this);
        tail = new TailContext(this);

        head.prev = null;
        head.next = tail;
        tail.prev = head;
        tail.next = null;
    }

    @Override
    public boolean doFilter(T t, O o) {
        return head.doFilter(t, o);
    }

    public synchronized Pipeline<T,O> addFirst(FilterHandler<T,O> handler) {
        AbstractFilterHandlerContext<T,O> newCtx = new DefaultFilterHandlerContext(this, handler);
        AbstractFilterHandlerContext<T,O> nextCtx = head.next;
        head.next = newCtx;
        newCtx.prev = head;
        newCtx.next = nextCtx;
        nextCtx.prev = newCtx;

        return this;
    }

    public synchronized Pipeline addFirst(List<FilterHandler> handlers) {
        if (handlers == null || handlers.isEmpty()) {
            return this;
        }

        int size = handlers.size();
        for (int i = 0; i < size; i++) {
            addFirst(handlers.get(size - i - 1));
        }

        return this;
    }

    public synchronized Pipeline addLast(FilterHandler handler) {
        AbstractFilterHandlerContext newCtx = new DefaultFilterHandlerContext(this, handler);
        AbstractFilterHandlerContext prevCtx = tail.prev;

        newCtx.prev = prevCtx;
        newCtx.next = tail;
        prevCtx.next = newCtx;
        tail.prev = newCtx;

        return this;
    }

    public synchronized Pipeline addLast(List<FilterHandler> handlers) {
        if (handlers == null || handlers.isEmpty()) {
            return this;
        }

        for (FilterHandler handler : handlers) {
            addLast(handler);
        }

        return this;
    }

    private static class HeadContext<T extends Object, O extends Object> extends AbstractFilterHandlerContext<T, O> {
        HeadContext(Pipeline pipeline) {
            super(pipeline);
        }

        @Override
        protected FilterHandler handler() {
            return null;
        }

        @Override
        public boolean doFilter(Object t, Object o) {
            AbstractFilterHandlerContext ctx = findNextCtx();
            if(ctx != null) {
                return ctx.doFilter(t, o);
            }
            return false;

        }
    }

    private static class TailContext extends AbstractFilterHandlerContext {
        TailContext(Pipeline pipeline) {
            super(pipeline);
        }

        @Override
        protected FilterHandler handler() {
            return null;
        }

        @Override
        public boolean doFilter(Object t, Object o) {
            AbstractFilterHandlerContext ctx = findNextCtx();
            if(ctx != null) {
                return ctx.doFilter(t, o);
            }
            return false;
        }
    }
}
